import React, { Component } from 'react'
import {
  TextField,
  Stack,
  DefaultButton,
  PrimaryButton,
  Nav,
  IconButton,
  Label,
  DefaultPalette,
} from 'office-ui-fabric-react'
import TextFieldTip from './textfieldTip.js'
import { initializeIcons } from '@uifabric/icons'
import {
  Dropdown,
  DropdownMenuItemType,
  IDropdownStyles,
  IDropdownOption,
} from 'office-ui-fabric-react/lib/Dropdown'
import {
  CommandBar,
  ICommandBarItemProps,
} from 'office-ui-fabric-react/lib/CommandBar'
import './index.css'

initializeIcons()

const vscode = acquireVsCodeApi()

const horizontalStackStyles = {
  root: {
    //   background: DefaultPalette.themeTertiary,
  },
}
const horizontalGapStackTokens = {
  childrenGap: 300,
  padding: 10,
}
const ScenarioHorizontalGapStackTokens= {
	childrenGap: 200,
	padding: 10,
  }

const stackTokens = {
  childrenGap: 50,
}
const stackStyles = {
  root: {},
}
const leftStackStyles = {
  root: {
    width: 280,
  },
}
const navStackStyles = {
  root: {
    width: 250,
    position: 'fixed',
  },
}
const columnProps = {
  tokens: {
    childrenGap: 50,
  },
  styles: {
    root: {
      maxWidth: 800,
    },
  },
}
const navStyles = {
  root: {
    width: 250,
    height: '70vh',
    overflowY: 'auto',
    marginTop: 50,
    groupContent: {
      marginBottom: 20,
    },
  },
}
const buttonStyles = {
  margin: 20,
}

const scenarioStackStyles = {
  root: {
    marginLeft: 30,
  },
}
const textFieldStyles={
	root: {
	  width:700,
	},
  }



const style = {
  collapsed: {
    display: 'none',
  },
  expanded: {
    display: 'block',
  },
}

const upIconProps = { iconName: 'ChevronUp' }
const downIconProps = { iconName: 'ChevronDown' }

let navLinkGroups = [
  {
    name: '版本(Version)',
    url: '',
    key: 'version',
    _name: 'version',
    _tip: '所使用的GitCourse解释器版本，目前只支持版本"1"',
  },
  {
    name: '课程标题(Title)',
    url: '',
    key: 'title',
    _name: 'title',
  },
  {
    name: '作者(Author)',
    url: '',
    key: 'author',
    _name: 'author',
  },
  {
    name: '课程简介(Description)',
    url: '',
    key: 'description',
    _name: 'description',
  },
  {
    name: '课程场景(Scenarios)',
    _name: 'scenarios',
    key: 'scenarios',
    links: [],
    _tip: '课程的场景，将会按顺序逐个进行解析',
  },
]

class CoursePage extends Component {
  constructor(props) {
    super(props)
    this.state = {
      title: '-1',
      version: '1',
      author: '-1',
      description: '-1',
      isCollapse: {},
    }
  }

  componentDidMount() {
    window.addEventListener('message', this.getMessage)
  }

  componentWillUnmount() {
    window.removeEventListener('message', this.getMessage)
  }

  getMessage = (event) => {
    const message = event.data // The JSON data our extension sent

    switch (message.command) {
      case 'load':
        let courseJson = message.data
        this.updateNav(courseJson)
        this.setState({
          ...courseJson,
        })
        break
      case 'run':
        break
      default:
        console.log(message)
        break
    }
  }
  //解析json部分
  updateNav = (courseJson) => {
    const scenarios = courseJson.scenarios
    let scenariosArr = scenarios.map((el, index) => {
      let stepArr = this.getStepArr(el.steps, index)

      let scenarioLinksArr = [
        {
          name: '场景标题(Title)',
          url: '',
          key: `scenarios${index}Title`,
          _name: 'title',
          _tip: '场景打开时显示的标题',
        },
        {
          name: '场景描述(Description)',
          url: '',
          key: `scenarios${index}Description`,
          _name: 'description',
        },
        {
          name: '容器镜像地址(Environment)',
          url: '',
          key: `scenarios${index}Environment`,
          _name: 'environment',
          _tip: '本场景所使用的容器镜像地址',
        },
        {
          name: '场景步骤(Steps)',
          key: `scenarios${index}Step`,
          url: '',
          _name: 'steps',
          links: stepArr,
          _tip:
            '	场景的步骤，将会按顺序逐个进行解析，以供学员分步骤完成本场景的学习',
        },
      ]
      //可选字段？
      if ('shell' in el) {
        scenarioLinksArr.splice(-1, 0, {
          name: '终端(Shell)',
          url: '',
          key: `scenarios${index}Shell`,
          _name: 'shell',
          _tip: '指定终端使用/bin/sh还是/bin/bash',
        })
      }
      if ('docker_endpoint' in el) {
        scenarioLinksArr.splice(-1, 0, {
          name: 'DOCKER服务器地址(Docker_endpoint)',
          url: '',
          key: `scenarios${index}Docker`,
          _name: 'docker_endpoint',
          _tip: '所使用的docker服务的地址，不指定则使用全局地址',
        })
      }
      return {
        name: `场景${index}`,
        key: `scenarios${index}`,
        url: '',
        links: scenarioLinksArr,
      }
    })
    navLinkGroups[4].links = scenariosArr
  }

  getStepArr = (steps, scenarioIndex) =>
    steps.map((el, index) => {
      let stepLinksArr = [
        {
          name: '步骤标题(Title)',
          url: '',
          key: `scenarios${scenarioIndex}Step${index}Title`,
          _name: 'title',
        },
        {
          name: 'MD文件路径(Text)',
          url: '',
          key: `scenarios${scenarioIndex}Step${index}Text`,
          _name: 'text',
          _tip: 'markdown文件的相对路径，用于在此步骤中展示',
        },
      ]
      //步骤可选字段
      if ('preload' in el) {
        stepLinksArr.push({
          name: 'JS脚本路径(Preload)',
          url: '',
          key: `scenarios${scenarioIndex}Step${index}Preload`,
          _name: 'preload',
          _tip: 'javascript脚本的相对路径，步骤初始化时在浏览器端执行',
        })
      }
      if ('program' in el) {
        stepLinksArr.push({
          name: 'Shell初始化脚本路径(Program)',
          url: '',
          key: `scenarios${scenarioIndex}Step${index}Program`,
          _name: 'program',
          _tip: 'shell脚本的相对路径，步骤初始化时在容器中执行',
        })
      }
      if ('check' in el) {
        stepLinksArr.push({
          name: 'Shell检查脚本路径(Check)',
          url: '',
          key: `scenarios${scenarioIndex}Step${index}Check`,
          _name: 'check',
          _tip:
            'shell脚本的相对路径，用户点击完成步骤时在容器中执行，用于检查完成情况。当脚本检查通过后应当输出1，否则用户不会进入下一步。',
        })
      }
      if ('extraTab' in el) {
        stepLinksArr.push({
          name: 'Shell检查脚本路径(ExtraTab)',
          url: '',
          key: `scenarios${scenarioIndex}Step${index}ExtraTab`,
          _name: 'extraTab',
          _tip:
            '除了默认的终端之外，可以额外使用的容器交互接口。将在一个iframe中访问指定的容器端口与路径。',
        })
      }

      return {
        name: `步骤${index}`,
        key: `scenarios${scenarioIndex}Step${index}`,
        url: '',
        links: stepLinksArr,
      }
    })

  setCollapse = (e, key) => {
    let collapse = this.state.isCollapse
    collapse[key] = !collapse[key]
    this.setState({
      isCollapse: collapse,
    })
  }
  //渲染部分
  renderStepStack = (step, scenarioIndex, stepIndex) => {
    const { scenarios } = this.state
    return (
      <Stack>
        <Label className={`scenarios${scenarioIndex}Step${stepIndex}`}>
          <Stack
            horizontal
            styles={horizontalStackStyles}
            tokens={horizontalGapStackTokens}
          >
            {`步骤${stepIndex}`}{' '}
            <CommandBar
              items={this.getStepCommandBarItems(scenarioIndex, stepIndex)}
            ></CommandBar>
          </Stack>
        </Label>
        <Stack styles={scenarioStackStyles}>
          {step.links.map((el) => (
            <Stack>
              <Stack
                horizontal
                styles={horizontalStackStyles}
              >
                <TextField
                  label={el.name}
                  defaultValue={
                    scenarios[scenarioIndex].steps[stepIndex][el._name]
                      ? scenarios[scenarioIndex].steps[stepIndex][el._name]
                      : ''
                  }
				  styles={textFieldStyles}
                  value={
                    scenarios[scenarioIndex].steps[stepIndex][el._name]
                      ? scenarios[scenarioIndex].steps[stepIndex][el._name]
                      : ''
                  }
                  className={el.key}
                  tip={el._tip}
                  onChange={(event, newValue) =>
                    this.onChangeStep(
                      newValue,
                      scenarioIndex,
                      stepIndex,
                      el._name,
                    )
                  }
                  onRenderLabel={this.onRenderLabel}
                />
				{el._name in { program: '', extraTab: '' } && (
					<Stack.Item align='end'>
                  <CommandBar
                    items={this.getStepAttributeCommandBarItems(
                      scenarioIndex,
                      stepIndex,
                      el._name,
                    )}
                  ></CommandBar></Stack.Item>
                )}
              </Stack>
            </Stack>
          ))}
        </Stack>
      </Stack>
    )
  }

  renderScenarioStack = (scenario, scenarioIndex) => {
    let { scenarios, isCollapse } = this.state
    return (
      <Stack>
        <Label className={`scenarios${scenarioIndex} scenariosHeading`}>
          <Stack horizontal styles={horizontalStackStyles} stackTokens={ScenarioHorizontalGapStackTokens}>
            <IconButton
              iconProps={isCollapse[scenario.key] ? upIconProps : downIconProps}
              onClick={(e) => this.setCollapse(e, scenario.key)}
            />
			<span> {`场景${scenarioIndex}`}</span>
           
            <CommandBar
              items={this.getScenarioCommandBarItems(scenarioIndex)}
            ></CommandBar>
          </Stack>
        </Label>
        <Stack
          styles={scenarioStackStyles}
          style={isCollapse[scenario.key] ? style.collapsed : style.expanded}
        >
          {scenario.links.map((el) => {
            if (el._name !== 'steps') {
              return (
                <TextField
                  label={el.name}
                  multiline={el._name === 'description'}
                  defaultValue={
                    scenarios[scenarioIndex][el._name]
                      ? scenarios[scenarioIndex][el._name]
                      : ''
                  }
                  value={
                    scenarios[scenarioIndex][el._name]
                      ? scenarios[scenarioIndex][el._name]
                      : ''
                  }
                  className={el.key}
                  tip={el._tip}
                  onChange={(event, newValue) =>
                    this.onChangeScenario(newValue, scenarioIndex, el._name)
                  }
                  onRenderLabel={this.onRenderLabel}
                />
              )
            } else {
              return (
                <>
                  <Label
                    className={`scenarios${scenarioIndex}Step stepHeading`}
                  >
                    <Stack
                      horizontal
                      styles={horizontalStackStyles}
                      tokens={horizontalGapStackTokens}
                    >
                      场景步骤{' '}
                      <CommandBar
                        items={this.getStepsCommandBarItems(scenarioIndex)}
                      ></CommandBar>
                    </Stack>

                  </Label>
                  {el.links.map((step, stepIndex) =>
                    this.renderStepStack(step, scenarioIndex, stepIndex),
                  )}
                </>
              )
            }
          })}
        </Stack>
      </Stack>
    )
  }

  renderCourseStack = (el, index) => {
    const value = this.state[el._name]
    if (el._name !== 'scenarios') {
      if (value !== '-1') {
        return (
          <TextField
            label={el.name}
            disabled={el._name === 'version'}
            multiline={el._name === 'description'}
            defaultValue={value}
            className={el.key}
            onRenderLabel={this.onRenderHeadingLabel}
            tip={el._tip}
            onChange={(event, newValue) =>
              this.onChangeCourse(newValue, el._name)
            }
          />
        )
      }
    }
  }

  onLinkClick = (event, item) => {
    const collapse = this.state.isCollapse
    if (item) {
      const [flag, key] = this.ifCollapse(collapse, item.key)

      if (flag) {
        collapse[key] = false
        this.setState(
          {
            isCollapse: collapse,
          },
          () => {
            let selector = `.${item.key}`
            let element = document.querySelector(selector)

            element.scrollIntoView()
          },
        )
      }

      let selector = `.${item.key}`
      let element = document.querySelector(selector)

      element.scrollIntoView()
    }
  }

  ifCollapse = (collapse, key) => {
    console.log(collapse, key, collapse[key], key.length, key.slice(10))
    if (collapse[key]) {
      return [true, key]
    }
    if (key.length > 10 && collapse[key.slice(0, 10)]) {
      console.log(key.slice(0, 10))
      return [true, key.slice(0, 10)]
    }
    return [false]
  }

  onRenderGroupHeader = (group) => {
    return (
      <h3 className="groupHeader" onClick={(e) => this.onLinkClick(e, group)}>
        {group.name}
      </h3>
    )
  }

  onRenderHeadingLabel = (props) => {
    return (
      <Label className=" heading" disabled={props.disabled}>
        {props.label}
        <TextFieldTip tip={props.tip} />
      </Label>
    )
  }

  onRenderLabel = (props, defaultRender) => {
    return (
      <Stack horizontal verticalAlign="center" tokens={stackTokens}>
        <span>{defaultRender(props)}</span>
        <TextFieldTip tip={props.tip} />
      </Stack>
    )
  }

  onClickSaveBtn = () => {
    vscode.postMessage({
      command: 'save',
      data: this.state,
    })
  }

  onClickDocBtn = () => {
    vscode.postMessage({
      command: 'openDoc',
    })
  }
  //修改状态部分
  onChangeCourse = (newValue, name) => {
    this.setState({
      [name]: newValue,
    })
  }
  onChangeScenario = (newValue, scenarioIndex, name) => {
    let newScenarios = this.state.scenarios
    newScenarios[scenarioIndex][name] = newValue
    this.setState({
      scenarios: newScenarios,
    })
  }
  onChangeStep = (newValue, scenarioIndex, stepIndex, name) => {
    let newScenarios = this.state.scenarios
    newScenarios[scenarioIndex].steps[stepIndex][name] = newValue
    this.setState({
      scenarios: newScenarios,
    })
  }

  //添加和删除内容
  //默认scenario内容
  getDefaultScenario = () => {
    return {
      title: '',
      shell: '',
      vscode_port: 1234,
      environment: '',
      description: '',
      steps: [this.getDefaultStep()],
    }
  }

  getDefaultStep = () => {
    return {
      title: '',
      text: '',
    }
  }

  //CommandBar内容定义
  getCourseCommandBarItems = () => {
    return [
      {
        key: 'newItem',
        text: 'New',
        cacheKey: 'myCacheKey',
        iconProps: { iconName: 'Add' },
        subMenuProps: {
          items: [
            {
              key: 'add',
              text: '添加场景',
              onClick: () =>
                this.onSpliceScenario(
                  this.state.scenarios.length,
                  0,
                  this.getDefaultScenario(),
                ),
            },
          ],
        },
      },
    ]
  }

  getScenarioCommandBarItems = (scenarioIndex) => {
    return [
      {
        key: 'deleteScenario',
        text: 'delete',
        cacheKey: 'myCacheKey',
        iconProps: { iconName: 'Add' },
        onClick: () => {
          this.onSpliceScenario(scenarioIndex, 1)
        },
      },
    ]
  }

  getStepsCommandBarItems = (scenarioIndex) => {
    return [
      {
        key: 'AddStep',
        text: 'add',
        cacheKey: 'myCacheKey',
        iconProps: { iconName: 'Add' },
        onClick: () => {
          this.onSpliceStep(
            scenarioIndex,
            this.state.scenarios[scenarioIndex].steps.length,
            0,
            this.getDefaultStep(),
          )
        },
      },
    ]
  }

  getStepCommandBarItems = (scenarioIndex, stepIndex) => {
    return [
      {
        key: 'newItem',
        text: '操作',
        cacheKey: 'myCacheKey',
        iconProps: { iconName: 'Add' },
        subMenuProps: {
          items: [
            {
              key: 'deleteStep',
              text: '删除步骤',
              onClick: () => {
                this.onSpliceStep(scenarioIndex, stepIndex, 1)
              },
            },
            {
              key: 'addScript',
              text: '添加Program',
              onClick: () => {
                this.onStepAddAttribute(scenarioIndex, stepIndex, 'program')
              },
            },
            {
              key: 'addStepBefore',
              text: '在上方添加步骤',
              onClick: () => {
                this.onSpliceStep(
                  scenarioIndex,
                  stepIndex,
                  0,
                  this.getDefaultStep(),
                )
              },
            },
            {
              key: 'addExtraTab',
              text: '添加ExtraTab',
              onClick: () => {
                this.onStepAddAttribute(scenarioIndex, stepIndex, 'extraTab')
              },
            },
          ],
        },
      },
    ]
  }

  getStepAttributeCommandBarItems = (
    scenarioIndex,
    stepIndex,
    attributeName,
  ) => {
    return [
      {
        key: 'delete' + attributeName,
        text: '删除',
        cacheKey: 'myCacheKey',
        iconProps: { iconName: 'Add' },
        onClick: () => {
          this.onStepDeleteAttribute(scenarioIndex, stepIndex, attributeName)
        },
      },
    ]
  }
  //向数组添加或删除元素
  //del: 删除置1,添加置0,同array的splice方法
  onSpliceScenario = (index, del, elementToAdd) => {
    let newState = this.state
    if (elementToAdd != undefined) {
      newState.scenarios.splice(index, del, elementToAdd)
    } else {
      newState.scenarios.splice(index, del)
    }
    this.changeStateAndUpdateNav(newState)
  }

  //添加或删除step
  onSpliceStep = (scenarioIndex, stepIndex, del, elementToAdd) => {
    let newState = this.state
    if (elementToAdd != undefined) {
      newState.scenarios[scenarioIndex].steps.splice(
        stepIndex,
        del,
        elementToAdd,
      )
    } else {
      newState.scenarios[scenarioIndex].steps.splice(stepIndex, del)
    }
    this.changeStateAndUpdateNav(newState)
  }

  //操作元素的属性
  //step添加属性
  onStepAddAttribute = (scenarioIndex, stepIndex, attributeName) => {
    let newState = this.state
    newState.scenarios[scenarioIndex].steps[stepIndex][attributeName] = ''
    this.changeStateAndUpdateNav(newState)
  }

  //step删除属性
  onStepDeleteAttribute = (scenarioIndex, stepIndex, attributeName) => {
    let newState = this.state
    delete newState.scenarios[scenarioIndex].steps[stepIndex][attributeName]
    this.changeStateAndUpdateNav(newState)
  }

  changeStateAndUpdateNav = (newState) => {
    this.updateNav(newState)
    this.setState(newState)
  }

  render() {
    return (
      <Stack horizontal tokens={stackTokens} styles={stackStyles}>
        <Stack styles={leftStackStyles}>
          <Stack styles={navStackStyles}>
            <Nav
              styles={navStyles}
              groups={navLinkGroups}
              onLinkClick={this.onLinkClick}
              onRenderGroupHeader={this.onRenderGroupHeader}
            />
            <PrimaryButton onClick={this.onClickSaveBtn} style={buttonStyles}>
              保存
            </PrimaryButton>
            <DefaultButton onClick={this.onClickDocBtn} style={buttonStyles}>
              官方文档
            </DefaultButton>
          </Stack>
        </Stack>
        <Stack.Item grow {...columnProps}>
          {navLinkGroups.map((heading, index) =>
            this.renderCourseStack(heading, index),
          )}

          <Label className="scenarios heading">
            <Stack
              horizontal
              styles={horizontalStackStyles}
              tokens={horizontalGapStackTokens}
            >
              <span>课程场景(Scenarios)</span>
              <CommandBar items={this.getCourseCommandBarItems()} />
            </Stack>
          </Label>
          {navLinkGroups[4].links.map((scenario, index) =>
            this.renderScenarioStack(scenario, index),
          )}
        </Stack.Item>
      </Stack>
    )
  }
}

export default CoursePage
export {vscode}
